/**
 * Copyright 2011 Honeywell Federal Manufacturing & Technologies, LLC. This material was produced under U.S. Government
 * contract DE-ACO4-01AL66850, Honeywell Federal Manufacturing & Technologies, LLC, (FM&T) with the U. S. Department of
 * Energy for the operation of the Kansas City Plant . The U.S. Government has rights to use, reproduce, and distribute
 * this software.  NEITHER THE GOVERNMENT NOR Honeywell Federal Manufacturing & Technologies, LLC, MAKES ANY WARRANTY,
 * EXPRESS OR IMPLIED, OR ASSUMES ANY LIABILITY FOR THE USE OF THIS SOFTWARE.  If software is modified to produce
 * derivative works, such modified software should be clearly marked, so as not to confuse it with the version available
 * from FM&T.
 *
 * Additionally, this program is free software; you can redistribute it and/or modify it under the terms of the GNU
 * General Public License Version 3 published by the Free Software Foundation. Accordingly, this program is distributed in
 * the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along with this library.
 * If not, see http://www.gnu.org/licenses/.
 */
package org.braintrain.tapestry.view;

import com.javaforge.tapestry.spring.annotations.InjectSpring;
import org.apache.tapestry.IRequestCycle;
import org.apache.tapestry.annotations.InjectPage;
import org.apache.tapestry.annotations.InjectState;
import org.apache.tapestry.annotations.Persist;
import org.braintrain.domain.*;
import org.braintrain.services.MessageService;
import org.braintrain.tapestry.aso.TestASO;

/**
 * Tapestry Test page.  This navigation page defines the test page.
 * This page displays a given test (with initialization, see init()), and allows the user
 * to take the test.
 * 
 * @author John Ericksen
 *
 */

public abstract class Test extends BrainTrainEditableNavigatablePage {
	
    //loop variables
    public abstract Question getQuestion();
    public abstract void setQuestion(Question q);
    
    public abstract Answer getAnswer();
    public abstract void setAnswer(Answer a);
    
    @Persist("session:page")
    public abstract boolean isSubmitted();
    public abstract void setSubmitted(boolean b);
    
    //page injections
    @InjectPage("EditTest")
    public abstract EditTest getEditTestPage();
    
    @InjectPage("TestRecordConfirm")
    public abstract TestRecordConfirm getTestRecordConfirmPage();
    
    @InjectState("testaso")
    public abstract TestASO getTestASO();
    
    @InjectSpring("messageService")
    public abstract MessageService getMessageService();

    
    public abstract boolean getEditTest();
    public abstract void setEditTest(boolean t);
    
    
        
    /**
     * Initialize the test:
     * setupTest() and put the test into the TestASO
     */
    public void init()
    {
        setSubmitted(false);
        if(getTestASO().getTest(getNavId()) == null)
        {

            TestData test = (TestData)getNavigation().getContent(isDeltaUser());
            test.setupTest();
            getTestASO().putTest(test, getNavId());
        }
    }
    
    /**
     * Returns the current test from the Test ASO
     * @return
     */
    public TestData getCurrentTest()
    {
       return getTestASO().getTest(getNavId());
    }
    
    /**
     * return the navigation module
     * @return
     */
    public Module getModule()
    {
        return getNavigation().getModule();
    }
    
  
    /**
     * Grade the current test after the test has been submitted from the user.
     * Actions:
     * 1. Correct test (see Test.gradeTest())
     * 2. Save the answers given to the answer log (right or wrong)
     * 3. If the test has been passed:
     *       email certificate, 
     *       log test completion,
     *       navigate to the next page
     * 4. If the test has not been passed return to the test page and display:
     *       incorrect responses,
     *       cleared incorrect answers (if option is selected)
     *       
     */
    public void gradeTest(IRequestCycle cycle)
    {
        setSubmitted(true);
        
        //determine if the current test is in the released state:
        boolean released = false;
        if(getNavigation() != null && getNavigation().getNullSafeContent().getValue() != null)
        {
            released = getCurrentTest().getId().equals(getNavigation().getNullSafeContent().getValue().getId());
        }
        
        int correct = getContentService().saveGradeTest(getNavigation(), getCurrentTest(), getBraintrainVisit().getAuthenticatedUser(), getBraintrainVisit().getUser());

        if(correct >= getCurrentTest().getNumberCorrectToPass())
        {
            if(getModule().isActive() && released)
            {
                Integer score = correct * 100 / getCurrentTest().getNumberOfQuestionsToUse();
                
                //continue to the test reporting confirmation page
                getTestRecordConfirmPage().activate(cycle, getNavId(), getParentNavId(), score);
                
            }
            else
            {
                //setup the next navigation
                    
                Navigation next = null;
                if(isDeltaUser())
                {
                    next = getNavigation().getDeltaNext();
                }
                else
                {
                    next = getNavigation().getNext();
                }
                    
                
                if(next != null)
                {
                    ((BrainTrainEditableNavigatablePage)cycle.getPage(next.getType().name()))
                        .activate(cycle, next.getId(), getParentNavId());
                }
                else if(getParentNavId() != null)
                {
                    ((BrainTrainEditableNavigatablePage)cycle.getPage(getParentNavigation().getType().name()))
                        .activate(cycle, getParentNavId(), null);
                }
                else if(isDeltaUser() && !getNavigation().isMainNavigation())
                {
                    getModuleAdminPage().activate(cycle, getNavigation().getModule().getId());
                }
                else
                {
                    getEvaluationPage().activate(cycle, getNavigation().getModule().getId());
                }
            }
            
            
        }
        else
        {
            getCurrentTest().clearIncorrectAnswers();
        }

        //todo:redirect
    }
    
    /**
     * Submit the given test to the EditTest page
     * @param cycle
     */
    public void editTestSubmit(IRequestCycle cycle)
    {
        getEditTestPage().activate(cycle, getNavId(), getParentNavId());
    }
    
    /**
     * Allow CM-Staff and ContentCreators to skip tests
     * @return
     */
    public boolean isTestCompleted()
    {
        return isDeltaUser();
    }
}
